home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Connection Tool ƒ / Definition.c < prev    next >
C/C++ Source or Header  |  1994-02-19  |  26KB  |  874 lines

  1. // ===========================================================================
  2. // "Connection Tool Skeleton in C" for the Communications Toolbox
  3. // 
  4. //    Copyright © 1994 Peter J. Creath
  5. //    All Rights Reserved Worldwide
  6. // ===========================================================================
  7.  
  8. #include <CRMSerialDevices.h>
  9. #include "ConnToolCommon.h"
  10.  
  11. // ===========================================================================
  12. // Function prototypes
  13. // ===========================================================================
  14. extern pascal long    main(ConnHandle hConn, short msg, long p1, long p2, CMCompletorRecord *pCompletor);
  15. extern CMErr    DoInit(ConnHandle hConn);
  16. extern CMErr    DoDispose(ConnHandle hConn);
  17. extern CMErr    DoSuspend(ConnHandle hConn);
  18. extern CMErr    DoResume(ConnHandle hConn);
  19. extern long        DoMenu(ConnHandle hConn, short menuID, short menuItem);
  20. extern void        DoEvent(ConnHandle hConn, EventRecord *theEvent);
  21. extern CMErr    DoActivate(ConnHandle hConn);
  22. extern CMErr    DoDeactivate(ConnHandle hConn);
  23. extern CMErr    DoIdle(ConnHandle hConn);
  24. extern CMErr    DoAbort(ConnHandle hConn);
  25. extern CMErr    DoRead(ConnHandle hConn, CMDataBuffer *pData, CMCompletorPtr pCompletor, long timeout);
  26. extern CMErr    DoWrite(ConnHandle hConn, CMDataBuffer *pData, CMCompletorPtr pCompletor, long timeout);
  27. extern CMErr    DoStatus(ConnHandle hConn, CMBufferSizes *bufferSize, long *theFlag);
  28. extern CMErr    DoListen(ConnHandle hConn, CMCompletorPtr pCompletor, long timeout);
  29. extern CMErr    DoAccept(ConnHandle hConn, Boolean accept);
  30. extern CMErr    DoClose(ConnHandle hConn, CMCompletorPtr pCompletor, long timeout);
  31. extern CMErr    DoOpen(ConnHandle hConn, CMCompletorPtr pCompletor, long timeout);
  32. extern CMErr    DoBreak(ConnHandle hConn, long duration, CMCompletorPtr pCompletor);
  33. extern CMErr    DoIOKill(ConnHandle hConn, short channel);
  34. extern CMErr    DoReset(ConnHandle hConn);
  35. extern CMErr    DoEnvirons(ConnHandle hConn, ConnEnvironRec *pEnvirons);
  36.  
  37. // ===========================================================================
  38. // main()
  39. //     This function is the entry point for the 'cdef' resource.  It passes control to the appropriate
  40. //     subroutines, depending on the incoming message.  This can probably remain unchanged.
  41. // ===========================================================================
  42. pascal long main(ConnHandle hConn, short msg, long p1, long p2, CMCompletorRecord *pCompletor)
  43. {
  44. long            rtnValue;
  45.  
  46.     switch (msg)
  47.         {
  48.             case cmInitMsg:
  49.                 rtnValue = DoInit(hConn);
  50.                 break;
  51.  
  52.             case cmDisposeMsg:
  53.                 rtnValue = DoDispose(hConn);
  54.                 break;
  55.  
  56.             case cmSuspendMsg:
  57.                 rtnValue = DoSuspend(hConn);
  58.                 break;
  59.  
  60.             case cmResumeMsg:
  61.                 rtnValue = DoResume(hConn);
  62.                 break;
  63.  
  64.             case cmMenuMsg:
  65.                 rtnValue = DoMenu(hConn, p1, p2);
  66.                 break;
  67.  
  68.             case cmEventMsg:
  69.                 DoEvent(hConn, (EventRecord *)p1);
  70.                 break;
  71.  
  72.             case cmActivateMsg:
  73.                 rtnValue = DoActivate(hConn);
  74.                 break;
  75.  
  76.             case cmDeactivateMsg:
  77.                 rtnValue = DoDeactivate(hConn);
  78.                 break;
  79.  
  80.             case cmIdleMsg:
  81.                 rtnValue = DoIdle(hConn);
  82.                 break;
  83.  
  84.             case cmAbortMsg:
  85.                 rtnValue = DoAbort(hConn);
  86.                 break;
  87.  
  88.             case cmReadMsg:
  89.                 rtnValue = DoRead(hConn, (CMDataBufferPtr)p1, pCompletor, p2);
  90.                 break;
  91.  
  92.             case cmWriteMsg:
  93.                 rtnValue = DoWrite(hConn, (CMDataBufferPtr)p1, pCompletor, p2);
  94.                 break;
  95.  
  96.             case cmStatusMsg:
  97.                 rtnValue = DoStatus(hConn, (CMBufferSizes *)p1, (long *)p2);
  98.                 break;
  99.  
  100.             case cmListenMsg:
  101.                 rtnValue = DoListen(hConn, (CMCompletorPtr)p1, p2);
  102.                 break;
  103.  
  104.             case cmAcceptMsg:
  105.                 rtnValue = DoAccept(hConn, (Boolean)p1);
  106.                 break;
  107.  
  108.             case cmCloseMsg:
  109.                 rtnValue = DoClose(hConn, (CMCompletorPtr)p1, p2);
  110.                 break;
  111.  
  112.             case cmOpenMsg:
  113.                 rtnValue = DoOpen(hConn, (CMCompletorPtr)p1, p2);
  114.                 break;
  115.  
  116.             case cmBreakMsg:
  117.                 rtnValue = DoBreak(hConn, p1, (CMCompletorPtr)p2);
  118.                 break;
  119.  
  120.             case cmIOKillMsg:
  121.                 rtnValue = DoIOKill(hConn, p1);
  122.                 break;
  123.             
  124.             case cmResetMsg:
  125.                 rtnValue = DoReset(hConn);
  126.                 break;
  127.  
  128.             case cmEnvironsMsg:
  129.                 rtnValue = DoEnvirons(hConn, (ConnEnvironRec *)p1);
  130.                 break;
  131.             
  132.             default:
  133.                 rtnValue = cmNotSupported;
  134.                 break;
  135.         }
  136.  
  137.     return (rtnValue);
  138. }
  139.  
  140. // ===========================================================================
  141. // DoInit()
  142. //    This function is called in response to a cmInitMsg.  If your tool allocates space for internal
  143. //    buffers in the .bufferArray field of the connection record, applications and the Connection
  144. //    Manager must NOT manipulate the space.  Also, your tools is responsible for freeing the space
  145. //    (in DoDispose).  You are not required to use the .bufferArray field.  This function should return
  146. //    an appropriate error, if any.
  147. // ===========================================================================
  148. CMErr DoInit(ConnHandle hConn)
  149. {
  150. CMErr            rtnValue;
  151. ConnPtr        pConn;
  152. Ptr                tempPtr;
  153. PrivatePtr    pPrivate;
  154. char                handleState;
  155.  
  156.     rtnValue = noErr;
  157.     handleState = HGetState((Handle)hConn);
  158.     HLock((Handle)hConn);
  159.     pConn = *hConn;
  160.     
  161.     pConn->flags |= cmData;                                            // Specify which channels this tool supports
  162.     pConn->flags &= (~cmAttn);
  163.     pConn->flags &= (~cmCntl);
  164.  
  165.     if (tempPtr = NewPtr(pConn->bufSizes[cmDataIn]))    // Allocate memory for the I/O buffers
  166.         {
  167.             pConn->bufferArray[cmDataIn] = tempPtr;
  168.  
  169.             if (tempPtr = NewPtr(pConn->bufSizes[cmDataOut]))
  170.                 {
  171.                     pConn->bufferArray[cmDataOut] = tempPtr;
  172.  
  173.                     if (tempPtr = NewPtr(sizeof(PrivateRecord)))
  174.                         {
  175.                             pPrivate = (PrivatePtr)tempPtr;
  176.                             // Fill in private data here
  177.                         }
  178.                     else
  179.                         {
  180.                             DisposPtr(pConn->bufferArray[cmDataIn]);
  181.                             DisposPtr(pConn->bufferArray[cmDataOut]);
  182.                             rtnValue = MemErr;
  183.                         }
  184.                 }
  185.             else
  186.                 {
  187.                     DisposPtr(pConn->bufferArray[cmDataIn]);
  188.                     rtnValue = MemErr;
  189.                 }
  190.         }
  191.     else
  192.         {
  193.             rtnValue = MemErr;
  194.         }
  195.  
  196.     HSetState((Handle)hConn, handleState);
  197.  
  198.     return (rtnValue);
  199. }
  200.  
  201. // ===========================================================================
  202. // DoDispose()
  203. //    This function is called in response to a cmDisposeMsg.  It should dispose of any buffers allocated
  204. //    in response to cmInitMsg and any private data storage (referenced off of .cmPrivate in the
  205. //    connection record).  It must NOT attempt to dispose of either .config or .oldConfig in the
  206. //    connection record, or of the connection record itself.  Doing so WILL cause a system crash!
  207. // ===========================================================================
  208. CMErr DoDispose(ConnHandle hConn)
  209. {
  210. PrivatePtr    pPrivate;
  211. CMErr            rtnValue;
  212. ConnPtr        pConn;
  213. char                handleState;
  214.  
  215.     rtnValue = noErr;
  216.     handleState = HGetState((Handle)hConn);
  217.     HLock((Handle)hConn);
  218.     pConn = *hConn;
  219.     pPrivate = (PrivatePtr)(pConn->cmPrivate);
  220.  
  221.     if (pPrivate->status & cmStatusOpen)                        // If the connection is open then call CMClose on it
  222.         {
  223.             rtnValue = CMClose(hConn, FALSE, (ProcPtr)0L, 0, TRUE);
  224.         }
  225.     
  226.     if (rtnValue == noErr)                                                // If the connection is happily closed, release memory
  227.         {
  228.             DisposPtr((Ptr)(pConn->cmPrivate));
  229.             DisposPtr((Ptr)(pConn->bufferArray[cmDataIn]));
  230.             DisposPtr((Ptr)(pConn->bufferArray[cmDataOut]));
  231.         }
  232.  
  233.     HSetState((Handle)hConn, handleState);
  234.  
  235.     return (rtnValue);
  236. }
  237.  
  238. // ===========================================================================
  239. // DoSuspend()
  240. //    This function is called in response to a cmSuspendMsg.  This should do anything needed (like
  241. //    remove a menu from the menu bar) in response to a suspend message.
  242. // ===========================================================================
  243. CMErr    DoSuspend(ConnHandle hConn)
  244. {
  245. CMErr    rtnValue;
  246. PrivatePtr    pPrivate;
  247.  
  248.     rtnValue = noErr;
  249.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  250.     
  251.     return (rtnValue);
  252. }
  253.  
  254. // ===========================================================================
  255. // DoResume()
  256. //    This function is called in response to a cmResumeMsg.  This should do anything needed (like add
  257. //    a menu to the menu bar) in response to a resume message.
  258. // ===========================================================================
  259. CMErr    DoResume(ConnHandle hConn)
  260. {
  261. CMErr    rtnValue;
  262. PrivatePtr    pPrivate;
  263.  
  264.     rtnValue = noErr;
  265.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  266.     
  267.     return (rtnValue);
  268. }
  269.  
  270. // ===========================================================================
  271. // DoMenu()
  272. //     This function handles the any menu event passed to it.  It should return FALSE if the menu was not
  273. //    handled and TRUE if it was.
  274. // ===========================================================================
  275. long        DoMenu(ConnHandle hConn, short menuID, short menuItem)
  276. {
  277. long        rtnValue;
  278. Boolean    isMine;
  279.  
  280.     rtnValue = noErr;
  281.     isMine = FALSE;                                // Perform some check here to see if the menu belongs to this tool
  282.     
  283.     if (isMine)
  284.         {
  285.             rtnValue = TRUE;
  286.             // process the menu command
  287.         }
  288.  
  289.     return (rtnValue);
  290. }
  291.  
  292. // ===========================================================================
  293. // DoEvent()
  294. //    This subroutine is called in response to a cmEventMsg.  It is called when an event occurs in a
  295. //    window associated with the connection tool.
  296. // ===========================================================================
  297. void        DoEvent(ConnHandle hConn, EventRecord *theEvent)
  298. {
  299. DialogPtr    theDialog;
  300. short        theItem;
  301.  
  302. #define CancelButton 2
  303.  
  304.     if (IsDialogEvent(theEvent))
  305.         {
  306.             if (DialogSelect(theEvent, &theDialog, &theItem))            // Find out which item was hit
  307.                 {
  308.                     switch (theItem)
  309.                         {
  310.                             case CancelButton:
  311.                                 // Cancel the connection
  312.                                 break;
  313.                         }
  314.                 }
  315.         }
  316.     else
  317.         {
  318.             // Handle the keyDown, updateEvt, mouseDown, and any other event here
  319.         }
  320. }
  321.  
  322. // ===========================================================================
  323. // DoActivate()
  324. //    This function is called in response to a cmActivateMsg.  This should do anything needed (like add
  325. //    a menu to the menu bar) in response to an activate message.
  326. // ===========================================================================
  327. CMErr    DoActivate(ConnHandle hConn)
  328. {
  329. CMErr    rtnValue;
  330. PrivatePtr    pPrivate;
  331.  
  332.     rtnValue = noErr;
  333.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  334.     
  335.     return (rtnValue);
  336. }
  337.  
  338. // ===========================================================================
  339. // DoDeactivate()
  340. //    This function is called in response to a cmDeactivateMsg.  This should do anything needed (like
  341. //    remove a menu from the menu bar) in response to a deactivate message.
  342. // ===========================================================================
  343. CMErr    DoDeactivate(ConnHandle hConn)
  344. {
  345. CMErr    rtnValue;
  346. PrivatePtr    pPrivate;
  347.  
  348.     rtnValue = noErr;
  349.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  350.     
  351.     return (rtnValue);
  352. }
  353.  
  354. // ===========================================================================
  355. // DoIdle()
  356. //    This function should check the status of any asynchronous routines and make sure all is well.
  357. // ===========================================================================
  358. CMErr    DoIdle(ConnHandle hConn)
  359. {
  360. CMErr    rtnValue;
  361. PrivatePtr    pPrivate;
  362.  
  363.     rtnValue = noErr;
  364.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  365.     
  366.     return (rtnValue);
  367. }
  368.  
  369. // ===========================================================================
  370. // DoAbort()
  371. //    This function is called in response to a cmAbortMsg.  It should abort the pending listen or open
  372. //    process.  If no listen or open processes are pending, it should return an error.
  373. // ===========================================================================
  374. CMErr    DoAbort(ConnHandle hConn)
  375. {
  376. CMErr    rtnValue;
  377. PrivatePtr    pPrivate;
  378.  
  379.     rtnValue = noErr;
  380.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  381.     
  382.     if (pPrivate->status & cmStatusOpening)                // If we're trying to open a connection
  383.         {
  384.             // Stop opening
  385.         }
  386.     else
  387.         {
  388.             if (pPrivate->status & cmStatusListenPend)    // If we're listening for a connection
  389.                 {
  390.                     // Stop listening
  391.                 }
  392.             else
  393.                 {
  394.                     return (cmNoRequestPending);                // We weren't doing either...
  395.                 }
  396.         }
  397.  
  398.     // Close the physical layer driver
  399.  
  400.     return (rtnValue);
  401. }
  402.  
  403. // ===========================================================================
  404. // DoRead()
  405. //    This function is called in response to a cmReadMsg.  It should read data into the buffers specified
  406. //    by pData.  If a channel is requested that is not supported by this tool, you should return a
  407. //    cmNotSupported error.  If the tools does not complete the read within the specified time
  408. //    (timeout, in ticks), it should pass back a timeout error.  If the timeout is -1, then there is no
  409. //    timeout.  If the timeout is 0, this should read as many bytes, up to toRead bytes, as it can in
  410. //    one read attempt.
  411. // ===========================================================================
  412. CMErr DoRead(ConnHandle hConn, CMDataBuffer *pData, CMCompletorPtr pCompletor, long timeout)
  413. {
  414. PrivatePtr    pPrivate;
  415. CMErr            rtnValue;
  416. ConnPtr        pConn;
  417. Boolean            doAsync;
  418. short            handleState;
  419.  
  420.     rtnValue = noErr;
  421.     pData->flags = 0;                                                // Set flags to zero, this tool does not support it
  422.     handleState = HGetState((Handle)hConn);
  423.     HLock((Handle)hConn);
  424.     pConn = *hConn;
  425.     pPrivate = (PrivatePtr)(pConn->cmPrivate);
  426.  
  427.     if (pPrivate->status & cmStatusOpen)                // Is a connection open?
  428.         {
  429.             if (pData->channel == cmData)
  430.                 {
  431.                     doAsync = FALSE;
  432.                     if (pCompletor)    doAsync = pCompletor->async;
  433.  
  434.                     // If async read then install VBL task to check timeout
  435.                     // Else check the available data to read in the driver buffer
  436.                     
  437.                     rtnValue = PBRead((ParmBlkPtr)&(pPrivate->myRBlk.theParamBlk), doAsync);
  438.                     
  439.                     if (rtnValue == noErr)
  440.                         {
  441.                             if ((pPrivate->myRBlk.theParamBlk.ioActCount == 0) && doAsync)
  442.                                 {
  443.                                     pData->count = 0;
  444.                                     pConn->asyncCount[cmDataIn] = 0;
  445.                                 }
  446.                             else
  447.                                 {
  448.                                     pData->count = pPrivate->myRBlk.theParamBlk.ioActCount;
  449.                                     pConn->asyncCount[cmDataIn] = pPrivate->myRBlk.theParamBlk.ioActCount;
  450.                                 }
  451.                         }
  452.                     else                                                    // There was an error during the read
  453.                         {
  454.                             pData->count = 0;
  455.                             pConn->errCode = rtnValue;
  456.                         }
  457.                 }
  458.             else                                                            // We currently only support the data channel
  459.                 {
  460.                     rtnValue = cmNotSupported;
  461.                 }
  462.         }
  463.     else                                                                    // There is no open connection
  464.         {
  465.             rtnValue = cmNotOpen;
  466.         }
  467.  
  468.     HSetState((Handle)hConn, handleState);
  469.  
  470.     return (rtnValue);
  471. }
  472.  
  473. // ===========================================================================
  474. // DoWrite()
  475. //    This function is called in response to a cmWriteMsg.  It should write data from the buffers
  476. //    specified by pData.  If a channel is requested that is not supported by this tool, you should return
  477. //    a cmNotSupported error.  If the tools does not complete the write within the specified time
  478. //    (timeout, in ticks), it should pass back a timeout error.  If the timeout is -1, then there is no
  479. //    timeout.  If the timeout is 0, this should write as many bytes as it can in one write attempt.
  480. // ===========================================================================
  481. CMErr DoWrite(ConnHandle hConn, CMDataBuffer *pData, CMCompletorPtr pCompletor, long timeout)
  482. {
  483. PrivatePtr    pPrivate;
  484. CMErr            rtnValue;
  485. Boolean            doAsync;
  486. ConnPtr        pConn;
  487. short            handleState;
  488.  
  489.     rtnValue = noErr;
  490.     pData->flags = 0;                                                // Set flags to zero, this tool does not support it
  491.     handleState = HGetState((Handle)hConn);
  492.     HLock((Handle)hConn);
  493.     pConn = *hConn;
  494.     pPrivate = (PrivatePtr)(pConn->cmPrivate);
  495.  
  496.     if ((pPrivate->status & cmStatusOpen))            // Is a connection open?
  497.         {
  498.             if (pData->channel == cmData)
  499.                 {
  500.                     doAsync = FALSE;
  501.                     if (pCompletor)    doAsync = pCompletor->async;
  502.                     
  503.                     // If async write then install VBL task to check timeout
  504.                     // Else check the available data to write to the driver buffer
  505.                     
  506.                     rtnValue = PBWrite((ParmBlkPtr)&(pPrivate->myWBlk.theParamBlk), doAsync);
  507.                     
  508.                     if (rtnValue == noErr)
  509.                         {
  510.                             if ((pPrivate->myWBlk.theParamBlk.ioActCount == 0) && doAsync)
  511.                                 {
  512.                                     pData->count = 0;
  513.                                     pConn->asyncCount[cmDataIn] = 0;
  514.                                 }
  515.                             else
  516.                                 {
  517.                                     pData->count = pPrivate->myWBlk.theParamBlk.ioActCount;
  518.                                     pConn->asyncCount[cmDataIn] = pPrivate->myWBlk.theParamBlk.ioActCount;
  519.                                 }
  520.                         }
  521.                     else                                                    // There was an error during the write
  522.                         {
  523.                             pData->count = 0;
  524.                             pConn->errCode = rtnValue;
  525.                         }
  526.                 }
  527.             else                                                            // We currently only support the data channel
  528.                 {
  529.                     rtnValue = cmNotSupported;
  530.                 }
  531.         }
  532.     else                                                                    // There is no open connection
  533.         {
  534.             rtnValue = cmNotOpen;
  535.         }
  536.  
  537.     HSetState((Handle)hConn, handleState);
  538.  
  539.     return (rtnValue);
  540. }
  541.  
  542. // ===========================================================================
  543. // DoStatus()
  544. //    This function is called in response to a cmStatusMsg.  It should return the status of the
  545. //    connection in hConn.  It should also return the sizes of the connection's buffers.  Finally, it
  546. //    should return the appropriate OSErr or CMErr.
  547. // ===========================================================================
  548. CMErr DoStatus(ConnHandle hConn, CMBufferSizes *bufferSize, long *theFlag)
  549. {
  550. PrivatePtr    pPrivate;
  551. CMErr            rtnValue;
  552. long                count;
  553.  
  554.     rtnValue = noErr;
  555.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  556.  
  557.     *theFlag = pPrivate->status;
  558.     if (pPrivate->status & cmStatusOpen)
  559.         {
  560.             rtnValue = SerGetBuf(pPrivate->outRefNum, &count);    // Check output driver buffer
  561.             *bufferSize[cmDataOut] = count;
  562.             rtnValue = SerGetBuf(pPrivate->inRefNum, &count);        // Check input driver buffer
  563.             *bufferSize[cmDataIn] = count;
  564.             if (count > 0)
  565.                 {
  566.                     *theFlag |= cmStatusDataAvail;                                // Set the data available bit
  567.                     *theFlag |= cmStatusOpen;                                    // The connection is established
  568.                 }
  569.         }
  570.     else
  571.         {
  572.             *bufferSize[cmDataIn] = 0;
  573.             *theFlag = 0;
  574.         }
  575.  
  576.     return (rtnValue);
  577. }
  578.  
  579.  
  580. // ===========================================================================
  581. // DoListen()
  582. //    This function is called in response to a cmListenMsg.  It should wait for an incoming connection
  583. //    request.  NOTE:  pCompletor is created in a local stack frame, so copy any of its contents that
  584. //    will be needed later.
  585. // ===========================================================================
  586. CMErr    DoListen(ConnHandle hConn, CMCompletorPtr pCompletor, long timeout)
  587. {
  588. PrivatePtr    pPrivate;
  589. CMErr            rtnValue;
  590. long                count;
  591.  
  592.     rtnValue = noErr;
  593.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  594.  
  595.     if (pPrivate->status & cmStatusOpen)
  596.         {
  597.             rtnValue = cmNotClosed;                        // The connection is already open. 
  598.         }
  599.     else
  600.         {
  601.             // Establish the physical layer driver (open the serial port, etc.)
  602.  
  603.             if (pCompletor->async)
  604.                 {
  605.                     // Do async listen call
  606.                     
  607.                     pPrivate->status |= cmStatusListenPend;
  608.                     
  609.                     // Issue VBL task to terminate the listen in a specified timeout
  610.                 }
  611.             else
  612.                 {
  613.                     // Do sync listen call and return error when timeout
  614.                 }
  615.         }
  616.     
  617.     return (rtnValue);
  618. }
  619.  
  620. // ===========================================================================
  621. // DoAccept()
  622. //    This function is called in response to a cmAcceptMsg.  It should accept or reject an incoming
  623. //    call based on the value of "accept" passed to it, it should clear the cmStatusIncomingCallPresent
  624. //    bit, and it should return the error, if any.
  625. // ===========================================================================
  626. CMErr DoAccept(ConnHandle hConn, Boolean accept)
  627. {
  628. PrivatePtr    pPrivate;
  629. CMErr            rtnValue;
  630.  
  631.     rtnValue = noErr;
  632.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  633.     
  634.     if (pPrivate->status & cmStatusOpen)                            // If the connection is already open, yell at the caller
  635.         {
  636.             rtnValue = cmNotClosed;
  637.         }
  638.     else
  639.         {
  640.             if (accept)
  641.                 {
  642.                     pPrivate->status |= cmStatusOpen;                // Set the open status bit
  643.                 }
  644.             else
  645.                 {
  646.                     // Terminate the logical connection listen process (hang up the modem, etc.)
  647.                     // Close the physical layer driver (close the serial port, etc.)
  648.                 }
  649.  
  650.             pPrivate->status &= ~cmStatusIncomingCallPresent;
  651.         }
  652.  
  653.     return (rtnValue);
  654. }
  655.  
  656. // ===========================================================================
  657. // DoClose()
  658. //    This function is called in response to a cmCloseMsg.  NOTE:  pCompletor is created in a local stack
  659. //    frame, so copy any of its contents that will be needed later.
  660. // ===========================================================================
  661. CMErr DoClose(ConnHandle hConn, CMCompletorPtr pCompletor, long timeout)
  662. {
  663. PrivatePtr    pPrivate;
  664. CMErr            rtnValue;
  665. short            err;
  666.  
  667.     rtnValue = noErr;
  668.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  669.  
  670.     if (pPrivate->status & cmStatusOpen)
  671.         {
  672.             // If break pending, kill break VBL
  673.             
  674.             // If now, kill pending reads and writes
  675.             // Else wait for pending reads and writes to clear
  676.             
  677.             if (err = CloseDriver(pPrivate->inRefNum))    rtnValue = err;            // Close input and output drivers
  678.             if (err = CloseDriver(pPrivate->outRefNum))    rtnValue = err;
  679.  
  680.             // Call completor routine here if async is closed
  681.         }
  682.     else
  683.         {
  684.             rtnValue = cmNotOpen;
  685.         }
  686.  
  687.     return (rtnValue);
  688. }
  689.  
  690. // ===========================================================================
  691. // DoOpen()
  692. //    This function is called in response to a cmOpenMsg.  NOTE:  pCompletor is created in a local stack
  693. //    frame, so copy any of its contents that will be needed later.  This routine is almost entirely
  694. //    protocol-specific.
  695. // ===========================================================================
  696. CMErr DoOpen(ConnHandle hConn, CMCompletorPtr pCompletor, long timeout)
  697. {
  698. PrivatePtr        pPrivate;
  699. CMErr                rtnValue;
  700. ConfigPtr            pConfig;
  701. char                    handleState;
  702. CRMSerialPtr    pSerial;
  703.  
  704.     rtnValue = noErr;
  705.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  706.     pConfig = (ConfigPtr)((**hConn).config);
  707.     
  708.     /* pSerial = (CRMSerialPtr)GetSerialPtr(pConfig->portName);    // Get the CRM device info
  709.     // You get to roll your own GetSerialPtr...use CRMSearch...*/
  710.  
  711.     // Check if drivers are already open.
  712.     // If they're already open, warn the application
  713.     
  714.     // First open the output driver, then the input driver
  715.     
  716.     handleState = HGetState((Handle)(pSerial->outputDriverName));
  717.     HLock((Handle)(pSerial->outputDriverName));
  718.     rtnValue = OpenDriver(*(pSerial->outputDriverName), &(pPrivate->outRefNum));
  719.     HSetState((Handle)(pSerial->outputDriverName), handleState);
  720.     if (rtnValue == 0)                                                                    // Output opened successfully
  721.         {
  722.             handleState = HGetState((Handle)(pSerial->inputDriverName));
  723.             HLock((Handle)(pSerial->inputDriverName));
  724.             rtnValue = OpenDriver(*(pSerial->inputDriverName), &(pPrivate->inRefNum));
  725.             HSetState((Handle)(pSerial->inputDriverName), handleState);
  726.             if (rtnValue == 0)                                                            // Input opened successfully
  727.                 {
  728.                     pPrivate->status = cmStatusOpen;
  729.                 }
  730.             else                                                                                // Input open failed
  731.                 {
  732.                     CloseDriver(pPrivate->outRefNum);                        // So close the output driver
  733.                 }
  734.         }
  735.  
  736.     // Call completor routine here if async is open
  737.  
  738.     return (rtnValue);
  739. }
  740.  
  741. // ===========================================================================
  742. // DoBreak()
  743. //    This function is called in response to a cmBreakMsg.  NOTE:  pCompletor is created in a local
  744. //    stack frame, so copy any of its contents that will be needed later.
  745. // ===========================================================================
  746. CMErr DoBreak(ConnHandle hConn, long duration, CMCompletorPtr pCompletor)
  747. {
  748. PrivatePtr    pPrivate;
  749. CMErr            rtnValue;
  750. short            err;
  751. long                foo;
  752.  
  753.     rtnValue = noErr;
  754.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  755.     
  756.     if (pPrivate->status & cmStatusOpen)
  757.         {
  758.             if (pPrivate->breakPending)
  759.                 {
  760.                     rtnValue = noErr;
  761.                 }
  762.             else
  763.                 {
  764.                     if (pCompletor->async)
  765.                         {
  766.                             // Do it asynchronously
  767.                             // Start the break
  768.                             // Start a timer (VBL or such) when it finishes it will turn off the break and
  769.                             // then call the completion routine if necessary.
  770.                         }
  771.                     else
  772.                         {
  773.                             // Start the break;
  774.                             Delay(duration, &foo);
  775.                             // End the break;
  776.                         }
  777.                 }
  778.         }
  779.     else
  780.         {
  781.             rtnValue = cmNotOpen;
  782.         }
  783.  
  784.     return (rtnValue);
  785. }
  786.  
  787. // ===========================================================================
  788. // DoIOKill()
  789. //    This function is called in response to a cmIOKillMsg.  It should terminate a pending asynchronous
  790. //    input or output request.
  791. // ===========================================================================
  792. CMErr DoIOKill(ConnHandle hConn, short channel)
  793. {
  794. PrivatePtr    pPrivate;
  795. CMErr            rtnValue;
  796. HIOParam        localBlk;
  797.  
  798.     rtnValue = noErr;
  799.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  800.     
  801.     switch (channel)
  802.         {
  803.             case cmDataIn:
  804.                 localBlk.ioRefNum = pPrivate->myRBlk.theParamBlk.ioRefNum;
  805.                 break;
  806.  
  807.             case cmDataOut:
  808.                 localBlk.ioRefNum = pPrivate->myWBlk.theParamBlk.ioRefNum;
  809.                 break;
  810.  
  811.             default:
  812.                 return (cmNotSupported);
  813.         }
  814.         
  815.     localBlk.ioCompletion = 0L;
  816.     rtnValue = PBKillIO((ParmBlkPtr)&localBlk, FALSE);
  817.     if (rtnValue) (**hConn).errCode = rtnValue;
  818.  
  819.     return (rtnValue);
  820. }
  821.  
  822. // ===========================================================================
  823. // DoReset()
  824. //    This function is called in response to a cmResetMsg.  It is entirely protocol-specific.
  825. // ===========================================================================
  826. CMErr DoReset(ConnHandle hConn)
  827. {
  828. PrivatePtr    pPrivate;
  829. CMErr            rtnValue;
  830.  
  831.     rtnValue = noErr;
  832.     pPrivate = (PrivatePtr)((**hConn).cmPrivate);
  833.     
  834.     // Reset your connection (protocol-dependent)
  835.     
  836.     return (rtnValue);
  837. }
  838.  
  839. // ===========================================================================
  840. // DoEnvirons()
  841. //    This function is called in response to a cmEnvironsMsg.  It should return information about the
  842. //    connection environment.
  843. // ===========================================================================
  844. CMErr DoEnvirons(ConnHandle hConn, ConnEnvironRec *pEnvirons)
  845. {
  846. PrivatePtr    pPrivate;
  847. CMErr            rtnValue;
  848. ConfigPtr        pConfig;
  849.  
  850.     rtnValue = noErr;
  851.     pConfig = (ConfigPtr)((**hConn).config);
  852.     
  853.     if (pEnvirons->version < curConnEnvRecVers)
  854.         {
  855.             rtnValue = envBadVers;
  856.         }
  857.     else
  858.         {
  859.             if (pEnvirons->version > 1)
  860.                 {
  861.                     rtnValue = envVersTooBig;
  862.                 }
  863.  
  864.             pEnvirons->dataBits                = pConfig->dataBits;
  865.             pEnvirons->baudRate                = pConfig->baudRate;
  866.             pEnvirons->swFlowControl    = (pConfig->shaker.fInX && pConfig->shaker.fXOn);
  867.             pEnvirons->hwFlowControl    = (pConfig->shaker.fDTR && pConfig->shaker.fCTS);
  868.             pEnvirons->flags                    = 0;
  869.             pEnvirons->channels                = cmData;
  870.         }
  871.  
  872.     return (rtnValue);
  873. }
  874.